(() => {
    // 可索引类型接口： 描述对象索引的类型，和相应索引返回值的类型

    // 1.数组
    interface NumberArray {
        [propName: number]: string
    }
    let numberArray: NumberArray = ['李白', '白居易']
    console.log(numberArray[0]);

    // 2.对象
    interface StringObj {
        [propsName: string]: number
    }
    let stringObj: StringObj = {
        a: 1,
        b: 2
    }
    console.log(stringObj['a']);

    interface NumberObj {
        [propName: number]: number
    }
    let numberObj: NumberObj = {
        0: 1,
        1: 2
    }
    console.log(numberObj[0]);


    // 3.类
    class Animal {
        name: string
    }
    class Dog extends Animal {
        breed: string
    }
    interface NotOkey {
        // number 最终会通过toString转成string，再去索引对象
        // 所以父类的范围必须比子类大，所以父类必须是string，子类必须是number，不能互换
        [propName: string]: Animal
        [propName: number]: Dog
    }

    // 
    interface NumberDictionary {
        [propName: string]: number
        length: number
        // name:string  // 报错，‘name’的类型与索引类型返回的类型不匹配
    }
    let numberDictionary: NumberDictionary = {
        type: 1,
        length: 2
    }


    // 
    interface Person {
        readonly name: string
        age: number
        [propName: string]: string | number
    }
    let person:Person ={
        name:'苏轼',
        age:18,
        skill:'作诗'
    }
    // person.name = '杜甫'  // 报错，readonly修饰后，只读不写
    person.age = 19
    console.log(person);


    // 4.索引前面可以设置为只读
    interface ReadonlyStringArray{
        readonly [propName:string]:string|number
    }
    let readonlyStringArray:ReadonlyStringArray = {
        type:1
    }
    // readonlyStringArray.type = 2  //// 报错，readonly修饰后，只读不写
})()